﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using interfaceOperadores;
using System.IO;
using System.Reflection;

namespace Calculadora
{
    class libreriasDinamicas
    {
        public static ICollection<iOperadores> cargarPlugins()
        {
            ICollection<iOperadores> toReturn = new List<iOperadores>();

            // Busca los archivos cuya extensión es DLL en el directorio path
            string[] listadoDLL = null;
            string path = System.Windows.Forms.Application.StartupPath + "\\operadores";         
            if (Directory.Exists(path))
               listadoDLL = Directory.GetFiles(path, "*.dll");

            //Mediante los nombres previamente encontrados, obtiene las dll ya compiladas
            ICollection<Assembly> listadoAssemblies = new List<Assembly>(listadoDLL.Length);
            foreach (string dll in listadoDLL)
            {
                AssemblyName an =  AssemblyName.GetAssemblyName(dll);
                Assembly assembly = Assembly.Load(an);
                listadoAssemblies.Add(assembly);
            }

            //Actualmente están cargados todos los assemblies en listadoAssemblies, por lo tanto hay que filtrar 
            //aquellos que serán utiles para la calculadora, es decir, aquellos que implementen la interfaz iOperando

            Type tipoDePlugin = typeof(iOperadores);
            ICollection<Type> pluginsUtiles = new List<Type>();
            foreach (Assembly assembly in listadoAssemblies)
            {
                if (assembly != null)
                {
                    //Obtiene los distintos tipos del assembly
                    Type[] tipos = assembly.GetTypes();
                    //Verifica si alguno de todos los tipos que se han obtenido corresponde con el tipoDePlugin que necesitamos
                    //de ser así lo agrega a la lista
                    foreach (Type tipo in tipos) { 
                        if (tipo.GetInterface(tipoDePlugin.FullName) != null)  
                                pluginsUtiles.Add(tipo);
                    }   
                }
            }
            //Creamos las instancias de los tipos
            foreach (Type tipo in pluginsUtiles)
            {
                iOperadores plugin = (iOperadores)Activator.CreateInstance(tipo);
                toReturn.Add(plugin);
            }

            return toReturn;
        }

    }
}
